package com.uyayo.blog.service.impl;

import com.uyayo.framework.common.exception.ParentNotFoundException;
import com.uyayo.framework.core.service.impl.BaseServiceImpl;
import com.uyayo.blog.entity.BlogIndustry;
import com.uyayo.blog.mapper.BlogIndustryMapper;
import com.uyayo.blog.model.BlogIndustryCondition;
import com.uyayo.blog.service.BlogIndustryService;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Objects;


@Service("blogIndustryService")
public class BlogIndustryServiceImpl extends BaseServiceImpl<BlogIndustry> implements BlogIndustryService {

	private final BlogIndustryMapper blogIndustryMapper;

	public BlogIndustryServiceImpl(BlogIndustryMapper blogIndustryMapper) {
		this.blogIndustryMapper = blogIndustryMapper;
	}

	@Override
	public List<BlogIndustry> selectBlogIndustry(BlogIndustryCondition blogIndustryCondition) {
		Example example = new Example(BlogIndustry.class);
		Example.Criteria criteria = example.createCriteria();
		criteria.andEqualTo(blogIndustryCondition);
		example.createCriteria();
		return blogIndustryMapper.selectByExample(example);
	}

	@Override
	public int selectCountByParentId(Long parentId) {
		BlogIndustry blogIndustry = new BlogIndustry();
		blogIndustry.setParentId(parentId);
		return blogIndustryMapper.selectCount(blogIndustry);
	}

	@Override
	public int saveBlogIndustry(BlogIndustry blogIndustry) throws ParentNotFoundException {
		Long parentId = blogIndustry.getParentId();
		if(!Objects.isNull(parentId)){
			BlogIndustry blogIndustryParent = selectByKey(parentId);
			if(blogIndustryParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
		}
		int count = blogIndustryMapper.insertSelective(blogIndustry);
		if(count >0){
			updateHasChildrennToParent(parentId);
		}
		return count;
	}

	/**
	 * 迭代检查选择的上级id是否是自己的子级
	 * @param parentIdOld 原上级id
	 * @param parentIdNew	新上级id
	 * @param blogIndustryChild 子资源
	 * @param blogIndustryParent 父资源
	 */
	private void recursiveCheckParentIsChildren(Long parentIdOld, Long parentIdNew, BlogIndustry blogIndustryChild, BlogIndustry blogIndustryParent){
		if (selectCountByParentId(blogIndustryChild.getId()) > 0) {
			Example example = new Example(BlogIndustry.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",blogIndustryChild.getId());
			List<BlogIndustry> blogIndustrys = blogIndustryMapper.selectByExample(example);
			if (!blogIndustrys.isEmpty()) {
				for(BlogIndustry blogIndustry:blogIndustrys){
					if(Objects.equals(blogIndustry.getId(),parentIdNew)){
						blogIndustryParent.setParentId(parentIdOld);
						blogIndustryMapper.updateByPrimaryKeySelective(blogIndustryParent);
					}else {
						recursiveCheckParentIsChildren(parentIdOld, parentIdNew, blogIndustry, blogIndustryParent);
					}
				}
			}
		}
	}
	@Override
	public int updateBlogIndustry(BlogIndustry blogIndustry) throws ParentNotFoundException {

		BlogIndustry blogIndustryOld = selectByKey(blogIndustry.getId());

		if(blogIndustry.getParentId()==null){
			blogIndustry.setParentId(0L);
		}

		Long parentId = blogIndustry.getParentId();
		if(parentId!=0){

			//获取修改的父级资源
			BlogIndustry blogIndustryParent = selectByKey(parentId);
			if(blogIndustryParent==null){
				throw new ParentNotFoundException("Parent not found!");
			}
			if (selectCountByParentId(blogIndustryOld.getId()) > 0) {
				Example example = new Example(BlogIndustry.class);
				Example.Criteria criteria = example.createCriteria();
				criteria.andEqualTo("parentId",blogIndustryOld.getId());
				List<BlogIndustry> blogIndustrys = blogIndustryMapper.selectByExample(example);
				if (!blogIndustrys.isEmpty()) {
					for(BlogIndustry blogIndustry_:blogIndustrys){
						if(Objects.equals(blogIndustry_.getId(),parentId)){
							blogIndustryParent.setParentId(blogIndustryOld.getParentId());
							blogIndustryMapper.updateByPrimaryKeySelective(blogIndustryParent);
						}else{
							recursiveCheckParentIsChildren(blogIndustryOld.getParentId(),blogIndustry.getParentId(),blogIndustry,blogIndustryParent);
						}
					}
				}
			}
		}
		if(selectCountByParentId(blogIndustry.getId())>0) {
			blogIndustry.setHasChildren(true);
		}else{
			blogIndustry.setHasChildren(false);
		}
		int count = blogIndustryMapper.updateByPrimaryKeySelective(blogIndustry);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(parentId);
		if(blogIndustryOld!=null){
			updateHasChildrennToParent(blogIndustryOld.getParentId());
		}
		return count;
	}

	/**
	 * 修改父资源是否含子资源
	 * @param parentId 父资源id
	 */
	private void  updateHasChildrennToParent(Long parentId){
		if(!Objects.isNull(parentId)){
			BlogIndustry blogIndustry = new BlogIndustry();
			blogIndustry.setId(parentId);
			if(selectCountByParentId(parentId)>0) {
				blogIndustry.setHasChildren(true);
			}else{
				blogIndustry.setHasChildren(false);
			}
			blogIndustryMapper.updateByPrimaryKeySelective(blogIndustry);
		}
	}

	@Override
	public int deleteBlogIndustry(Long id) {

		if (selectCountByParentId(id) > 0) {
			Example example = new Example(BlogIndustry.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",id);
			List<BlogIndustry> blogIndustrys = blogIndustryMapper.selectByExample(example);
			if (!blogIndustrys.isEmpty()) {
				for(BlogIndustry blogIndustry:blogIndustrys){
					recursiveDelete( blogIndustry);
				}
			}
		}
		return delete(id);
	}

	/**
	 * 递归删除资源
	 * @param blogIndustry 资源
	 */
	private void recursiveDelete(BlogIndustry blogIndustry){

		if (selectCountByParentId(blogIndustry.getId()) > 0) {
			Example example = new Example(BlogIndustry.class);
			Example.Criteria criteria = example.createCriteria();
			criteria.andEqualTo("parentId",blogIndustry.getId());
			List<BlogIndustry> blogIndustrys = blogIndustryMapper.selectByExample(example);
			if (!blogIndustrys.isEmpty()) {
				for(BlogIndustry blogIndustryChild:blogIndustrys){
					recursiveDelete(blogIndustryChild);
				}
			}
		}
		delete(blogIndustry.getId());
	}

	public int delete(Long id) {
		BlogIndustry blogIndustry = blogIndustryMapper.selectByPrimaryKey(id);
		int count = blogIndustryMapper.deleteByPrimaryKey(id);
		if(count<=0){
			return count;
		}
		updateHasChildrennToParent(blogIndustry!=null?blogIndustry.getParentId():null);
		return count;
	}
}
